package ks.client.lobby;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import arch.MyLobbyInitialization;

import ks.client.WindowManager;
import ks.client.interfaces.ILobbyInitialize;

/**
 * Splash frame which starts the GUI. User is presented with ability
 * to connect to the (preconfigured) KombatGames server by either
 * logging in using existing account information of registering for
 * a new account.
 * <p>
 * Logic delegated to RegisterButtonController and ConnectButtonController.
 * <p>
 * Note for the purpose of easily integrating client-side TableManagerGUI
 * and UserManagerGUI, this class will take these objects in and pass them
 * along to the lobby as needed. This is not necessarily an ideal situation,
 * but it allows the work to continue. 
 * 
 * @author George Heineman
 */
public class ConnectFrame extends JFrame {

	/** Keep Eclipse happy. */
	private static final long serialVersionUID = 1L;

	/** Panel containing all GUI widgets. */
	JPanel panel;

	/** Callback routine for lobby initialization. */
	ILobbyInitialize lobbyInit;

	/** GUI elements for which we have interaction. */
	JTextField loginUserText = null;
	JPasswordField loginPassText = null;

	JPasswordField registerPassText = null;
	JPasswordField registerConfirmPassText = null;
	JButton registerButton = null;
	JButton connectButton = null;
	JTextArea statusA = null;

	/** Helper method to get registration password. */
	public JPasswordField getRegisterPassText() { return registerPassText; }

	/** Helper method to get confirmation password. */
	public JPasswordField getRegisterConfirmPassText() { return registerConfirmPassText; }

	/** Helper method to get loginUser text. */
	public JTextField getLoginUserText() { return loginUserText; }

	/** Helper method to get loginUser text. */
	public JPasswordField getLoginPassText() { return loginPassText; }

	/** Helper method to get status text area. */
	public JTextArea getStatus() { return statusA; }

	/**
	 * Construct and center the ConnectFrame.
	 * 
	 * Parameter was added 3/6/2011 to ensure clients could properly initialize with my 
	 * new code. Please check out {@link MyLobbyInitialization} as an example class that 
	 * you will need to write with your code.
	 * 
	 * @param init 
	 */
	public ConnectFrame(ILobbyInitialize init) {
		lobbyInit = init;

		setSize(480, 180);
		init();

		WindowManager.centerWindow(this);
	}

	/**
	 * Initialize the entities and layout of the GUI.
	 */
	private void init() {
		setTitle("Connect to KombatGames");
		setResizable(false);

		if (panel == null) {

			JLabel loginTextL = new JLabel("Login with existing Account");
			JLabel loginUserL = new JLabel("User:");
			JLabel loginPassL = new JLabel("Password:");
			loginUserText = getNumericField(); 
			loginPassText = getPasswordField();

			// registration select password.
			registerPassText = getPasswordField();
			registerConfirmPassText = getPasswordField();
			JLabel registerPasswordL = new JLabel("Password");
			JLabel registerConfirmPassL = new JLabel("Confirm :");

			connectButton = getConnectButton();

			JLabel registerTextL = new JLabel("Create new Account");
			registerButton = getRegisterButton();

			JPanel orP = new JPanel();
			orP.setMinimumSize(new Dimension (100, 30));
			orP.add(new JLabel("OR"));

			// errors go here
			statusA = new JTextArea(2, 30);
			statusA.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
			statusA.setBackground(Color.yellow);
			statusA.setLineWrap(true);
			statusA.setWrapStyleWord(false);
			statusA.setEditable(false);
			statusA.setText("this is a messa");
			statusA.setVisible(false);

			panel = new JPanel();
			GroupLayout layout = new GroupLayout(panel);
			panel.setLayout(layout);
			layout.setAutoCreateGaps(true);
			layout.setAutoCreateContainerGaps(true);

			// Horizontal first
			layout.setHorizontalGroup(layout.createSequentialGroup()
					.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
							.addComponent(loginTextL)
							.addGroup(layout.createSequentialGroup()
									.addComponent(loginUserL)
									.addComponent(loginUserText))
									.addGroup(layout.createSequentialGroup()
											.addComponent(loginPassL)
											.addComponent(loginPassText))
											.addComponent(connectButton))
											.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
													.addComponent(orP)
													.addComponent(statusA))
													.addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
															.addComponent(registerTextL)
															.addGroup(layout.createSequentialGroup()
																	.addComponent(registerPasswordL)
																	.addComponent(registerPassText))
																	.addGroup(layout.createSequentialGroup()
																			.addComponent(registerConfirmPassL)
																			.addComponent(registerConfirmPassText))
																			.addComponent(registerButton))
			);

			// Vertical next.
			layout.setVerticalGroup(layout.createSequentialGroup()
					.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
							.addComponent(loginTextL)
							.addComponent(registerTextL))
							.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
									.addComponent(loginUserL)
									.addComponent(loginUserText)
									.addComponent(registerPasswordL)
									.addComponent(registerPassText))
									.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
											.addComponent(loginPassL)
											.addComponent(loginPassText)
											.addComponent(registerConfirmPassL)
											.addComponent(registerConfirmPassText))
											.addComponent(orP)
											.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
													.addComponent(connectButton)
													.addComponent(statusA)
													.addComponent(registerButton))
			);

			panel.setBackground(SystemColor.control);
		}

		add(panel);
	}

	/**
	 * Creates and returns text field of appropriate size.
	 * 	
	 * @return java.awt.TextField	
	 */
	JTextField getTextField() {
		JTextField tf = new JTextField(40);

		return tf;
	}

	/**
	 * Creates and returns a text field in which only numbers can be typed.
	 * 
	 * @return
	 */
	JTextField getNumericField() {
		// this specialized constructor will properly ensure that the 
		// formatted text field only accepts LONGS from now on out.
		NumberFormat fi = NumberFormat.getInstance();
		fi.setParseIntegerOnly(true);
		fi.setGroupingUsed(false);
		final JTextField tf = new JFormattedTextField(fi);

		// note that pesky programmers can still type "-" and get it accepted!
		return tf;
	}

	/**
	 * Creates and returns password field of appropriate size.
	 * 
	 * @return java.awt.TextField	
	 */
	JPasswordField getPasswordField() {
		JPasswordField pf = new JPasswordField(40);

		return pf;
	}

	/**
	 * Prepare Register button and install controller to deal with requests to connect.
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getRegisterButton() {
		if (registerButton == null) {
			registerButton = new JButton();
			registerButton.setText("Register");

			registerButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					new RegisterButtonController(ConnectFrame.this).process(lobbyInit);
				}

			});
		}

		return registerButton;
	}

	/**
	 * Prepare Connect button and install controller to deal with requests to connect.
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getConnectButton() {
		if (connectButton == null) {
			connectButton = new JButton();
			connectButton.setText("Connect");

			connectButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					new ConnectButtonController(ConnectFrame.this).process(lobbyInit);
				}
			});
		}
		return connectButton;
	}

	/** 
	 * Helper method to set error and show its status. 
	 */
	public void setError(String string) {
		statusA.setText(string);
		statusA.setVisible(true);
	}

	/**
	 * Helper method to clear error.
	 */
	public void clearError() {
		statusA.setText("");
		statusA.setVisible(false);
	}

	/**
	 * Extract value and wipe password from the given JPasswordField.
	 * 
	 * @param p   password field to extract.
	 * @return
	 */
	String extractPassword(JPasswordField p) {
		char chars[] = p.getPassword();

		// eliminates from memory safely
		String password = new String("");
		for (char c : chars) {
			password = password + c;
		}
		for (int i = 0; i < chars.length; i++) {
			chars[i] = '\0';   // protect.
		}

		return password;
	}

}
